#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
验证工具模块

提供各种数据验证、格式检查等工具函数
"""

import re
import json
import ipaddress
from typing import Any, Dict, List, Optional, Union
from urllib.parse import urlparse


def is_valid_email(email: str) -> bool:
    """
    验证邮箱格式
    
    Args:
        email: 邮箱地址
        
    Returns:
        是否为有效邮箱格式
    """
    if not email or not isinstance(email, str):
        return False
    
    pattern = r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$'
    return bool(re.match(pattern, email))


def is_valid_url(url: str) -> bool:
    """
    验证URL格式
    
    Args:
        url: URL地址
        
    Returns:
        是否为有效URL格式
    """
    if not url or not isinstance(url, str):
        return False
    
    try:
        result = urlparse(url)
        return all([result.scheme, result.netloc])
    except Exception:
        return False


def is_valid_ip(ip: str) -> bool:
    """
    验证IP地址格式
    
    Args:
        ip: IP地址
        
    Returns:
        是否为有效IP地址
    """
    if not ip or not isinstance(ip, str):
        return False
    
    try:
        ipaddress.ip_address(ip)
        return True
    except ValueError:
        return False


def is_valid_port(port: Union[str, int]) -> bool:
    """
    验证端口号
    
    Args:
        port: 端口号
        
    Returns:
        是否为有效端口号
    """
    try:
        port_num = int(port)
        return 1 <= port_num <= 65535
    except (ValueError, TypeError):
        return False


def is_valid_json(json_str: str) -> bool:
    """
    验证JSON格式
    
    Args:
        json_str: JSON字符串
        
    Returns:
        是否为有效JSON格式
    """
    if not json_str or not isinstance(json_str, str):
        return False
    
    try:
        json.loads(json_str)
        return True
    except (json.JSONDecodeError, TypeError):
        return False


def is_valid_phone(phone: str, country_code: str = 'CN') -> bool:
    """
    验证手机号格式
    
    Args:
        phone: 手机号
        country_code: 国家代码
        
    Returns:
        是否为有效手机号格式
    """
    if not phone or not isinstance(phone, str):
        return False
    
    # 移除所有非数字字符
    phone_digits = re.sub(r'\D', '', phone)
    
    if country_code == 'CN':
        # 中国手机号：11位，以1开头
        pattern = r'^1[3-9]\d{9}$'
        return bool(re.match(pattern, phone_digits))
    else:
        # 其他国家的基本验证：7-15位数字
        return 7 <= len(phone_digits) <= 15


def is_strong_password(password: str, min_length: int = 8) -> bool:
    """
    验证密码强度
    
    Args:
        password: 密码
        min_length: 最小长度
        
    Returns:
        是否为强密码
    """
    if not password or not isinstance(password, str):
        return False
    
    if len(password) < min_length:
        return False
    
    # 检查是否包含大写字母、小写字母、数字和特殊字符
    has_upper = bool(re.search(r'[A-Z]', password))
    has_lower = bool(re.search(r'[a-z]', password))
    has_digit = bool(re.search(r'\d', password))
    has_special = bool(re.search(r'[!@#$%^&*(),.?":{}|<>]', password))
    
    return sum([has_upper, has_lower, has_digit, has_special]) >= 3


def validate_required_fields(data: Dict[str, Any], required_fields: List[str]) -> List[str]:
    """
    验证必填字段
    
    Args:
        data: 数据字典
        required_fields: 必填字段列表
        
    Returns:
        缺失的字段列表
    """
    missing_fields = []
    
    for field in required_fields:
        if field not in data or data[field] is None or data[field] == '':
            missing_fields.append(field)
    
    return missing_fields


def validate_data_types(data: Dict[str, Any], type_mapping: Dict[str, type]) -> List[str]:
    """
    验证数据类型
    
    Args:
        data: 数据字典
        type_mapping: 字段类型映射
        
    Returns:
        类型错误的字段列表
    """
    type_errors = []
    
    for field, expected_type in type_mapping.items():
        if field in data and data[field] is not None:
            if not isinstance(data[field], expected_type):
                type_errors.append(f"{field} should be {expected_type.__name__}")
    
    return type_errors


def sanitize_input(input_str: str, max_length: Optional[int] = None) -> str:
    """
    清理输入字符串
    
    Args:
        input_str: 输入字符串
        max_length: 最大长度
        
    Returns:
        清理后的字符串
    """
    if not isinstance(input_str, str):
        return ""
    
    # 移除前后空格
    cleaned = input_str.strip()
    
    # 移除潜在的危险字符
    cleaned = re.sub(r'[<>"\']', '', cleaned)
    
    # 限制长度
    if max_length and len(cleaned) > max_length:
        cleaned = cleaned[:max_length]
    
    return cleaned


def is_valid_date_format(date_str: str, format_str: str = '%Y-%m-%d') -> bool:
    """
    验证日期格式
    
    Args:
        date_str: 日期字符串
        format_str: 日期格式
        
    Returns:
        是否为有效日期格式
    """
    if not date_str or not isinstance(date_str, str):
        return False
    
    try:
        from datetime import datetime
        datetime.strptime(date_str, format_str)
        return True
    except ValueError:
        return False


def validate_file_size(file_size: int, max_size: int) -> bool:
    """
    验证文件大小
    
    Args:
        file_size: 文件大小（字节）
        max_size: 最大允许大小（字节）
        
    Returns:
        是否在允许范围内
    """
    return 0 <= file_size <= max_size


def validate_file_extension(filename: str, allowed_extensions: List[str]) -> bool:
    """
    验证文件扩展名
    
    Args:
        filename: 文件名
        allowed_extensions: 允许的扩展名列表
        
    Returns:
        是否为允许的扩展名
    """
    if not filename or not isinstance(filename, str):
        return False
    
    import os
    file_ext = os.path.splitext(filename)[1].lower()
    return file_ext in [ext.lower() for ext in allowed_extensions]


def is_safe_path(path: str) -> bool:
    """
    验证路径安全性（防止路径遍历攻击）
    
    Args:
        path: 文件路径
        
    Returns:
        是否为安全路径
    """
    if not path or not isinstance(path, str):
        return False
    
    # 检查是否包含危险的路径遍历字符
    dangerous_patterns = ['../', '..\\', '../', '..\\\\']
    
    for pattern in dangerous_patterns:
        if pattern in path:
            return False
    
    # 检查是否为绝对路径（在某些情况下可能不安全）
    import os
    if os.path.isabs(path):
        return False
    
    return True


def validate_range(value: Union[int, float], min_val: Optional[Union[int, float]] = None, 
                  max_val: Optional[Union[int, float]] = None) -> bool:
    """
    验证数值范围
    
    Args:
        value: 要验证的值
        min_val: 最小值
        max_val: 最大值
        
    Returns:
        是否在指定范围内
    """
    try:
        num_value = float(value)
        
        if min_val is not None and num_value < min_val:
            return False
        
        if max_val is not None and num_value > max_val:
            return False
        
        return True
    except (ValueError, TypeError):
        return False